<!-- 模拟愤怒的小鸟 -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>模拟愤怒的小鸟</title>
    <style>
        canvas {
            background-color: black;
        }
    </style>
</head>

<body>
    <canvas id="canvas"></canvas>
</body>
<script src="../utils.js"></script>
<script>
    // 小球绘制
    class Ball {
        constructor(options) {
            this.x = 0;
            this.y = 0;
            this.r = 200;
            this.fillStyle = 'blue';
            this.strokeStyle = 'black';
            // 小球缩放
            this.scaleX = 1;
            this.scaleY = 1;
            // 定义小球移动速度
            this.vx = 0;
            this.vy = 0;
            // 小球透明度
            this.alpha = 1;
            Object.assign(this, options);
            return this;
        }
        render(ctx) {
            let { x, y, r, fillStyle, strokeStyle, scaleX, scaleY, alpha } = this;
            // 保存绘图环境
            ctx.save();
            // 开始绘制
            // ctx.beginPath();
            ctx.beginPath();
            ctx.translate(x, y);
            ctx.scale(scaleX, scaleY);
            ctx.strokeStyle = strokeStyle;
            ctx.fillStyle = fillStyle;

            ctx.globalAlpha = alpha;

            ctx.arc(0, 0, r, 0, Math.PI * 2);


            ctx.fill();
            ctx.stroke();
            ctx.restore();
            ctx.closePath();
            return this;
        }
        // 判断点是否在图形内部
        isInside(x, y) {
            let dis = Math.sqrt(Math.pow(x - this.x, 2) + Math.pow(y - this.y, 2))
            return dis < this.r;
        }
    }

    // 绘制方形
    class Rect {
        constructor(options) {
            this.x = 0;
            this.y = 0;
            this.w = 100;
            this.h = 50;
            this.fillStyle = 'blue';
            this.strokeStyle = 'black';
            // 小球缩放
            this.scaleX = 1;
            this.scaleY = 1;
            // 定义小球移动速度
            this.vx = 0;
            this.vy = 0;
            // 小球透明度
            this.alpha = 1;
            Object.assign(this, options);
            return this;
        }
        render(ctx) {
            let { x, y, w, h, fillStyle, strokeStyle, scaleX, scaleY, alpha } = this;
            // 保存绘图环境
            ctx.save();
            // 开始绘制
            // ctx.beginPath();
            ctx.beginPath();
            // ctx.translate(x, y);
            ctx.scale(scaleX, scaleY);
            ctx.strokeStyle = strokeStyle;
            ctx.fillStyle = fillStyle;

            ctx.globalAlpha = alpha;
            // console.log('x', y);

            // 绘制矩形
            ctx.rect(x - w / 2, y - h / 2, w, h);

            ctx.fill();
            ctx.stroke();
            ctx.restore();
            ctx.closePath();
            return this;
        }
        // 判断点是否在图形内部
        isInside(x, y) {
            return x <= this.w / 2 && x > this.w / 2 && y <= this.h / 2 && y > this.h / 2;
        }
    }


    let canvas = document.getElementById('canvas');
    let ctx = canvas.getContext('2d');

    let W = canvas.width = 800;
    let H = canvas.height = 600;

    // 重力加速度，f为摩擦力
    let g = 0.3, f = 0.98;
    let mouse = C.getOffset(canvas);
    // 缓动系数
    let easing = 0.03;
    // 是否是动作状态
    let moving = false;
    // 上次坐标，用于计算斜率
    let lastX, lastY;

    const ball = new Ball({
        x: 50,
        y: 500,
        r: 30,
        fillStyle: 'rgb(70, 227, 51)'
    });

    const box = new Rect({
        x: 620,
        y: 480,
        w: 120,
        h: 70
    });

    canvas.addEventListener('click', function (e) {
        moving = true;
        // 计算初始速度，目标点是鼠标位置
        ball.vx = (mouse.x - ball.x) * easing;
        ball.vy = (mouse.y - ball.y) * easing;
        // 初始化时的坐标
        lastX = ball.x;
        lastY = ball.y;
    });

    function checkHit() {
        // 斜率=(y1-y2)/(x1-x2) 通过两个点获取斜率
        const k1 = (ball.y - lastY) / (ball.x - lastX);
        // 根据一元一次方程，获取截距
        const b1 = lastY - k1 * lastX;
        // 矩形盒子的斜率和截距
        const k2 = 0;
        const b2 = ball.y;
        // k1*x + b1 = k2*x + b2
        // 获取小球与盒子的交点坐标
        const cx = (b2 - b1) / (k1 - k2);
        const cy = k1 * cx + b1;
        if (cx - ball.r / 2 > box.x && cx + ball.r / 2 < box.x + box.w && ball.y - ball.r > box.y) {
            console.log('小球进去了！');
            return true;
        }
    }

    function ballMove() {
        ball.vx *= f;
        ball.vy *= f;
        ball.vy += g;

        ball.x += ball.vx;
        ball.y += ball.vy;

        // 边界处理和碰撞检测，小球出界或者进入箱子重置
        if (checkHit() || ball.x - ball.r > W || ball.x + ball.r < 0 || ball.y - ball.r > H || ball.y + ball.r < 0) {
            moving = false;
            ball.x = 50;
            ball.y = 500;
        }

        lastX = ball.x;
        lastY = ball.y;
    }

    // 没有运动的时候，显示鼠标和小球的连线
    function drawLine() {
        ctx.beginPath();
        ctx.lineWidth = 2;
        ctx.strokeStyle = 'rgb(251, 78, 104)';
        ctx.lineTo(mouse.x, mouse.y);
        ctx.lineTo(ball.x, ball.y);
        ctx.stroke();
    }

    (function drawFrame() {
        window.requestAnimationFrame(drawFrame);

        ctx.clearRect(0, 0, W, H);

        if (moving) {
            ballMove();
        } else {
            drawLine();
        }

        ball.render(ctx);
        box.render(ctx);
    })();
</script>

</html>